package fun.tan90.easy.binlog.manager.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.annotation.UseDataSource;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowUtil;
import fun.tan90.easy.binlog.manager.model.cmd.MetricCpuQueryCmd;
import fun.tan90.easy.binlog.manager.model.cmd.MetricThreadQueryCmd;
import fun.tan90.easy.binlog.manager.model.vo.MetricCacheStatsVo;
import fun.tan90.easy.binlog.manager.model.vo.MetricCpuLineChartVo;
import fun.tan90.easy.binlog.manager.service.MetricService;
import fun.tan90.easy.binlog.manager.model.cmd.MetricJvmQueryCmd;
import fun.tan90.easy.binlog.manager.model.vo.MetricJvmLineChartVo;
import fun.tan90.easy.binlog.manager.model.vo.MetricThreadLineChartVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * description TODO
 * company 铁人科技
 *
 * @author 陈浩杰
 * @date 2023/12/28 13:21
 */
@Slf4j
@UseDataSource("tdengine")
@Service
public class MetricServiceImpl implements MetricService {

    @Override
    public List<MetricCpuLineChartVo> cpu(MetricCpuQueryCmd queryCmd) {
        String sql = "select _ts as time, system_cpu_usage * 100 as system_cpu_usage, process_cpu_usage * 100 as process_cpu_usage from metric_cpu where work_id = ? and _ts >= ? and _ts < ?";
        List<Row> rows = Db.selectListBySql(sql, queryCmd.getWorkId(), queryCmd.getStartTime(), queryCmd.getEndTime());
        return RowUtil.toEntityList(rows, MetricCpuLineChartVo.class);
    }

    @Override
    public List<MetricJvmLineChartVo> jvm(MetricJvmQueryCmd queryCmd) {
        String sql = "select _ts as time, max / 1048576 as max, used / 1048576 as used, committed / 1048576 as committed from metric_jvm where work_id = ? and jvm_type = ? and _ts >= ? and _ts < ?";
        List<Row> rows = Db.selectListBySql(sql, queryCmd.getWorkId(), queryCmd.getJvmType(), queryCmd.getStartTime(), queryCmd.getEndTime());
        return RowUtil.toEntityList(rows, MetricJvmLineChartVo.class);
    }

    @Override
    public Double jvmPercent(String workId, String jvmType) {
        String sql = "select sum(used * 100) / sum(max) as percent from metric_jvm where work_id = ? and jvm_type = ?";
        Row row = Db.selectOneBySql(sql, workId, jvmType);
        return row.getDouble("percent");
    }

    @Override
    public List<MetricThreadLineChartVo> thread(MetricThreadQueryCmd queryCmd) {
        String col = "max, used, committed";
        String tag = queryCmd.getTag();
        if ("thread_states".equals(tag)) {
            col = "timed_waiting, newable, runnable, blocked, waiting, terminated";
        } else if ("threads".equals(tag)) {
            col = "live, daemon, peak";
        }
        String sql = "select _ts as time, {} from metric_thread where work_id = ? and _ts >= ? and _ts < ?";
        List<Row> rows = Db.selectListBySql(StrUtil.format(sql, col), queryCmd.getWorkId(), queryCmd.getStartTime(), queryCmd.getEndTime());
        return RowUtil.toEntityList(rows, MetricThreadLineChartVo.class);
    }

    @Override
    public List<MetricCacheStatsVo> cacheStats(String workId) {
        String sql = "select *, _ts as time from caffeine_cache_stats where work_id = ? and _ts = ?";
        List<Row> rows = Db.selectListBySql(sql, workId, DateUtil.beginOfDay(new Date()));
        return RowUtil.toEntityList(rows, MetricCacheStatsVo.class);
    }
}
